import { ref, type Ref } from "vue";
import streamSaver from "streamsaver";
import { getFilenameFromDisposition } from "@/utils/tools";
import { http } from "@/utils/http";

export interface StreamDownloadOptions {
  method?: "GET" | "POST" | "PUT" | "DELETE";
  params?: Record<string, string | number | boolean>;
  data?: any;

  // 仅针对 CSV 的过滤选项（只有在响应确认为 CSV 时才会生效）
  csvKeepColumns?: Array<string | number>; // 需要保留的列（列名或索引）
  csvDelimiter?: string; // 默认 ","
  csvHasHeader?: boolean; // 默认 true（首行是表头）
  textEncoding?: string; // 默认 "utf-8"
}

// 文件流下载文件
const extFromContentType = (ct: string | undefined | null) => {
  if (!ct) return "txt";
  const mime = ct.split(";")[0].trim().toLowerCase();
  const map: Record<string, string> = {
    "text/plain": "txt",
    "text/csv": "csv",
    "text/html": "html",
    "text/markdown": "md",
    "application/json": "json",
    "application/pdf": "pdf",
    "application/zip": "zip",
    "application/octet-stream": "bin",
    "application/vnd.ms-excel": "xls",
    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "xlsx",
    "application/msword": "doc",
    "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
      "docx",
    "application/vnd.openxmlformats-officedocument.presentationml.presentation":
      "pptx",
    "image/png": "png",
    "image/jpeg": "jpg",
    "image/gif": "gif",
    "image/webp": "webp",
    "image/svg+xml": "svg",
    "audio/mpeg": "mp3",
    "audio/wav": "wav",
    "video/mp4": "mp4",
    "application/x-ndjson": "ndjson",
    "text/event-stream": "eventstream"
  };
  return map[mime] || "txt";
};

// 简易 CSV 行分割/合并：不处理引号/转义的复杂情况
function splitCsvLine(line: string, delimiter: string): string[] {
  return line.split(delimiter);
}
function joinCsvLine(cells: string[], delimiter: string): string {
  return cells.join(delimiter);
}

// 计算需要保留的列索引（支持列名或索引）
function computeKeepIdx(
  headers: string[],
  keep: Array<string | number>
): number[] {
  const idxs: number[] = [];
  for (const k of keep) {
    if (typeof k === "number") {
      if (k >= 0 && k < headers.length) idxs.push(k);
    } else {
      // 精确匹配；如需忽略大小写可在此处做标准化
      const i = headers.indexOf(k);
      if (i !== -1) idxs.push(i);
    }
  }
  return Array.from(new Set(idxs));
}

// 创建一个“边读边过滤”的 CSV Reader（轻量版）
function createCsvFilterReaderSimple(
  baseReader: ReadableStreamDefaultReader<Uint8Array>,
  options: {
    keepColumns: Array<string | number>;
    delimiter?: string;
    hasHeader?: boolean;
    encoding?: string;
  }
): ReadableStreamDefaultReader<Uint8Array> {
  const delimiter = options.delimiter ?? ",";
  const hasHeader = options.hasHeader ?? true;
  const encoding = options.encoding ?? "utf-8";

  const decoder = new TextDecoder(encoding);
  const encoder = new TextEncoder();

  let buffer = "";
  let headerParsed = !hasHeader;
  let keepIdx: number[] = [];

  const stream = new ReadableStream<Uint8Array>({
    async pull(controller) {
      const { done, value } = await baseReader.read();
      if (done) {
        if (buffer.length > 0) {
          let line = buffer;
          buffer = "";
          if (line.endsWith("\r")) line = line.slice(0, -1);
          if (!headerParsed) {
            const headers = splitCsvLine(line, delimiter);
            keepIdx = computeKeepIdx(headers, options.keepColumns);
            headerParsed = true;
            const filtered =
              joinCsvLine(
                keepIdx.map(i => headers[i] ?? ""),
                delimiter
              ) + "\n";
            controller.enqueue(encoder.encode(filtered));
          } else {
            const cells = splitCsvLine(line, delimiter);
            const filtered =
              joinCsvLine(
                keepIdx.map(i => cells[i] ?? ""),
                delimiter
              ) + "\n";
            controller.enqueue(encoder.encode(filtered));
          }
        }
        controller.close();
        return;
      }

      const chunkText = decoder.decode(value, { stream: true });
      buffer += chunkText;

      let idx: number;
      while ((idx = buffer.indexOf("\n")) !== -1) {
        let line = buffer.slice(0, idx);
        buffer = buffer.slice(idx + 1);
        if (line.endsWith("\r")) line = line.slice(0, -1);

        if (!headerParsed) {
          const headers = splitCsvLine(line, delimiter);
          keepIdx = computeKeepIdx(headers, options.keepColumns);
          headerParsed = true;
          const filtered =
            joinCsvLine(
              keepIdx.map(i => headers[i] ?? ""),
              delimiter
            ) + "\n";
          controller.enqueue(encoder.encode(filtered));
        } else {
          const cells = splitCsvLine(line, delimiter);
          const filtered =
            joinCsvLine(
              keepIdx.map(i => cells[i] ?? ""),
              delimiter
            ) + "\n";
          controller.enqueue(encoder.encode(filtered));
        }
      }
    },
    cancel(reason) {
      baseReader.cancel(reason);
    }
  });

  return stream.getReader();
}

export function useStreamDownload() {
  const loading: Ref<boolean> = ref(false);
  const progress: Ref<number> = ref(0);

  async function download(
    url: string,
    options: StreamDownloadOptions = {}
  ): Promise<void> {
    loading.value = true;
    progress.value = 0;

    // 1. 拿到 reader/total/disposition/contentType
    const {
      reader: baseReader,
      total,
      disposition,
      contentType
    } = await http.streamDownload(url, {
      method: options.method,
      params: options.params,
      data: options.data
    });

    // 2. 解析文件名
    const filename =
      getFilenameFromDisposition(disposition) ||
      `download_${new Date().getTime()}.${extFromContentType(contentType)}`;

    // 仅在 CSV 时考虑过滤
    const lowerCT = contentType?.toLowerCase() ?? "";
    const isCsv =
      lowerCT.startsWith("text/csv") || filename.toLowerCase().endsWith(".csv");

    // 3. 根据条件包装 reader：仅 CSV 且传了 csvKeepColumns 时启用过滤
    let reader = baseReader as ReadableStreamDefaultReader<Uint8Array>;
    if (isCsv && options.csvKeepColumns && options.csvKeepColumns.length > 0) {
      reader = createCsvFilterReaderSimple(baseReader, {
        keepColumns: options.csvKeepColumns,
        delimiter: options.csvDelimiter ?? ",",
        hasHeader: options.csvHasHeader ?? true,
        encoding: options.textEncoding ?? "utf-8"
      });
    }

    // 4. 写出（StreamSaver 优先）
    if (reader && "createWriteStream" in streamSaver) {
      // 确保你的 public/ 下有 sw.js，或自行配置 service worker
      const fileStream = streamSaver.createWriteStream(filename);
      const writer = fileStream.getWriter();
      let received = 0;

      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        await writer.write(value!);
        received += value!.length;
        if (total) progress.value = Math.floor((received / total) * 100);
      }

      await writer.close();
    } else {
      // 降级：拼 chunk + Blob 下载
      const chunks: Uint8Array[] = [];
      let received = 0;
      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        chunks.push(value!);
        received += value!.length;
        if (total) progress.value = Math.floor((received / total) * 100);
      }
      const blob = new Blob(chunks, {
        type: contentType ?? "application/octet-stream"
      });
      const link = document.createElement("a");
      link.href = URL.createObjectURL(blob);
      link.download = filename;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      URL.revokeObjectURL(link.href);
    }

    loading.value = false;
  }

  return {
    loading,
    progress,
    download
  };
}
